package com.ibl.rover.lite.common.db;

import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import com.ibl.rover.lite.client.Helper.DatabaseBeanHelper;
import com.ibl.rover.lite.common.bean.BaseBean;

public class SQLLiteDatabaseImpl extends DatabaseManager {

	private SQLiteDatabase sqLiteDatabase;

	public static SQLLiteDatabaseImpl getInstance(DatabaseBeanHelper helper) {
		return new SQLLiteDatabaseImpl(helper);
	}

	public SQLLiteDatabaseImpl(DatabaseBeanHelper helper) {
		DatabaseOpenHelper openHelper = new DatabaseOpenHelper(helper);
		sqLiteDatabase = openHelper.getWritableDatabase();
	}

	public class DatabaseOpenHelper extends SQLiteOpenHelper {

		private DatabaseBeanHelper helper;

		public DatabaseOpenHelper(DatabaseBeanHelper helper) {
			super(helper.getContext(), helper.getDatabaseName(), null, helper
					.getDatabaseVersion());
			this.helper = helper;
		}

		@Override
		public void onCreate(SQLiteDatabase database) {
			SQLLiteDatabaseImpl.this.sqLiteDatabase = database;
			helper.onDatabaseCreate(SQLLiteDatabaseImpl.this);
		}

		@Override
		public void onUpgrade(SQLiteDatabase database, int oldVersion,
				int newVersion) {
			SQLLiteDatabaseImpl.this.sqLiteDatabase = database;

		}

	}

	@Override
	public <T extends BaseBean> long saveBean(T bean) {
		SQLiteStatement statement = sqLiteDatabase.compileStatement(bean
				.getInsertQuery());
		bean.bind(statement);
		return statement.executeInsert();
	}

	@Override
	public <T extends BaseBean> void saveBean(List<T> bean)
			throws BaseException {

		SQLiteStatement statement;
		try {
			sqLiteDatabase.beginTransaction();

			for (BaseBean t : bean) {
				statement = sqLiteDatabase.compileStatement(t.getInsertQuery());
				t.bind(statement);
				statement.executeInsert();
				
			}
			sqLiteDatabase.setTransactionSuccessful();
		} catch (Exception e) {
			throw new BaseException("Database Save List Exception Occured  :"
					+ e.getMessage());
		} finally {
			sqLiteDatabase.endTransaction();
		}
	}

	@Override
	public <T extends BaseBean> int deleteBean(T bean) {

		return sqLiteDatabase.delete(bean.getTableName(), "_ID=?",
				new String[] { String.valueOf(bean.get_id()) });
	}

	@Override
	public <T extends BaseBean> int updateBean(T bean) {
		ContentValues contentValues = bean.bindContentValues();
		return sqLiteDatabase.update(bean.getTableName(), contentValues,
				"_ID=?", new String[] { String.valueOf(bean.get_id()) });

	}

	@Override
	public <T extends BaseBean> T findBeanById(T bean) {
		Cursor cursor = sqLiteDatabase.query(bean.getTableName(), null,
				"_ID=?", new String[] { String.valueOf(bean.get_id()) }, null,
				null, null);

		if (!cursor.moveToNext()) {
			return null;
		}

		bean.cursorBind(cursor);
		return bean;
	}

	@Override
	public <T extends BaseBean> List<T> findAllBean(Class<T> bean)
			throws BaseException {
		T beanInstance;
		Cursor cursor = null;
		try {
			sqLiteDatabase.beginTransaction();
			beanInstance = bean.newInstance();
			cursor = sqLiteDatabase.query(beanInstance.getTableName(),
					null, null, null, null, null, null);
			List<T> beansList = new ArrayList<T>(cursor.getCount());

			while (cursor.moveToNext()) {
				T baseBean = beanInstance.cursorBind(cursor);
				beansList.add(baseBean);

			}
			return beansList;
		} catch (Exception e) {
			throw new BaseException("SQl Exception :" + e.getMessage());

		} finally {
			if (cursor != null)
				cursor.close();
			sqLiteDatabase.setTransactionSuccessful();
			sqLiteDatabase.endTransaction();
		}

	}

	@Override
	public <T extends BaseBean> T findBeanById(Class<T> bean, long id)
			throws BaseException {
		T beanInstance;
		Cursor cursor = null;
		try {
			beanInstance = bean.newInstance();
			cursor = sqLiteDatabase.query(beanInstance.getTableName(),
					null, "_ID=?", new String[] { String.valueOf(id) }, null,
					null, null);

			if (!cursor.moveToNext())
				return null;
			else if (cursor.getCount() > 1) {
				return beanInstance.cursorInit(cursor);
			} else {
				return null;
			}

		} catch (Exception e) {
			throw new BaseException("SQl Exception :" + e.getMessage());

		} finally {
			if (cursor != null)
				cursor.close();
			sqLiteDatabase.endTransaction();
		}

	}

	@Override
	public <T extends BaseBean> Criteria<T> generateCriteria(Class<T> bean) {

		return new Criteria<T>(bean, this);
	}

	@Override
	public Cursor executeSQL(String sql, String[] selectionArgs) {

		return sqLiteDatabase.rawQuery(sql, selectionArgs);
	}

	@Override
	public void executeScaler(String sql) throws BaseException {
		try {
			sqLiteDatabase.execSQL(sql);
		} catch (SQLException ex) {
			throw new BaseException("[Exception occured : " + ex.getMessage());
		}
	}

	@Override
	public <T extends BaseBean> int updateBean(T bean,
			UpdatebeanCriteria beranCriteria) {

		return sqLiteDatabase.update(bean.getTableName(),
				beranCriteria.getUpdateBeanMap(bean),
				beranCriteria.getUpdateCriteria(bean), null);
	}

	@Override
	public <T extends BaseBean> int updateBean(List<T> entityList,
			UpdatebeanCriteria beanCriteria) {
		int count = 0;

		sqLiteDatabase.beginTransaction();
		try {
			for (T bean : entityList) {
				count += sqLiteDatabase.update(bean.getTableName(),
						beanCriteria.getUpdateBeanMap(bean),
						beanCriteria.getUpdateCriteria(bean), null);
			}
		} catch (SQLiteException e) {
			try {
				throw new BaseException("SQL Exception Occurred: "
						+ e.getMessage());
			} catch (BaseException e1) {

				e1.printStackTrace();
			}
		} finally {
			sqLiteDatabase.endTransaction();
		}
		return count;
	}

	@Override
	public <T extends BaseBean> int deleteBean(T entity,
			UpdatebeanCriteria beanCriteria) {
		return sqLiteDatabase.delete(entity.getTableName(),
				beanCriteria.getUpdateCriteria(entity), null);
	}

	@Override
	<T extends BaseBean> List<T> findBean(Class<T> bean, String where,
			String orderBy) throws BaseException {

		Cursor cursor = null;
		try {
			T beanInstance = bean.newInstance();

			cursor = sqLiteDatabase.query(beanInstance.getTableName(), null,
					where, null, null, null, orderBy);
			List<T> list = new ArrayList<T>(cursor.getCount());
			while (cursor.moveToNext()) {
				T beanBind = beanInstance.cursorBind(cursor);
				list.add(beanBind);
			}
			return list;
		} catch (Exception e) {
			throw new BaseException("SQL Exception :" + e.getMessage());
		} finally {
			cursor.close();
		}

	}

	@Override
	public <T extends BaseBean> Cursor executeDistinctSQL(Class<T> bean,
			String[] selectionArgs) throws BaseException {
		Cursor cursor = null;
		try {
			T beanInstance = bean.newInstance();
			cursor = sqLiteDatabase.query(true, beanInstance.getTableName(),
					selectionArgs, null, null, null, null, null, null);
		} catch (Exception e) {
			throw new BaseException("SQL Exceptipon:" + e.getMessage());
		}
		return cursor;
	}
}
